<?php

namespace magein\sms;

class Utils
{
    private static $defaultUserAgent = '';

    /**
     * @param $raw
     * @return string
     */
    public static function hexEncodeHashSha256($raw): string
    {
        return self::hexEncode(self::hash($raw, 'ACS3-RSA-SHA256'));
    }

    /**
     * @param $raw
     * @return string
     */
    public static function hexEncode($raw): string
    {
        if (is_array($raw)) {
            $raw = Utils::toString($raw);
        }
        return bin2hex($raw);
    }

    /**
     * @param $raw
     * @param $signatureAlgorithm
     * @return array|string
     */
    public static function hash($raw, $signatureAlgorithm)
    {
        $str = self::toString($raw);
        switch ($signatureAlgorithm) {
            case 'ACS3-HMAC-SHA256':
            case 'ACS3-RSA-SHA256':
                $res = hash('sha256', $str, true);
                return Utils::toBytes($res);
        }

        return [];
    }

    /**
     * Convert a string(utf8) to bytes.
     *
     * @param string $string
     *
     * @return array|string the return bytes
     */
    public static function toBytes($string)
    {
        if (self::isBytes($string)) {
            return $string;
        }
        $bytes = [];
        for ($i = 0; $i < \strlen($string); ++$i) {
            $bytes[] = \ord($string[$i]);
        }

        return $bytes;
    }

    /**
     * Convert a bytes to string(utf8).
     *
     * @param array|string $bytes
     *
     * @return string the return string
     */
    public static function toString($bytes): string
    {
        if (is_string($bytes)) {
            return $bytes;
        }
        $str = '';
        foreach ($bytes as $ch) {
            $str .= \chr($ch);
        }

        return $str;
    }

    /**
     * Parse it by JSON format.
     *
     * @param string $jsonString
     *
     * @return array the parsed result
     */
    public static function parseJSON(string $jsonString): array
    {
        return json_decode($jsonString, true);
    }

    /**
     * Generate a nonce string.
     *
     * @return string the nonce string
     */
    public static function getNonce(): string
    {
        return md5(uniqid() . uniqid(md5(microtime(true)), true));
    }

    /**
     * Get an UTC format string by current date, e.g. 'Thu, 06 Feb 2020 07:32:54 GMT'.
     *
     * @return string the UTC format string
     */
    public static function getDateUTCString(): string
    {
        return gmdate('D, d M Y H:i:s T');
    }

    /**
     * @return false|string
     */
    public static function getTimestamp()
    {
        return gmdate('Y-m-d\\TH:i:s\\Z');
    }

    /**
     * If not set the real, use default value.
     *
     * @param string $real
     * @param string $default
     *
     * @return string
     */
    public static function defaultString($real, $default = ''): string
    {
        return null === $real ? $default : $real;
    }

    /**
     * If not set the real, use default value.
     *
     * @param int|null $real
     * @param int $default
     *
     * @return int the return number
     */
    public static function defaultNumber($real, $default = 0): int
    {
        if (null === $real) {
            return $default;
        }

        return (int)$real;
    }


    /**
     * Check one value is unset.
     *
     * @param mixed $value
     *
     * @return bool if unset, return true
     */
    public static function isUnset(&$value = null): bool
    {
        return !isset($value);
    }

    /**
     * Stringify the value of map.
     *
     * @param array|null $map
     *
     * @return array the new stringified map
     */
    public static function stringifyMapValue($map): array
    {
        if (null === $map) {
            return [];
        }
        foreach ($map as &$node) {
            if (is_numeric($node)) {
                $node = (string)$node;
            } elseif (null === $node) {
                $node = '';
            } elseif (\is_bool($node)) {
                $node = true === $node ? 'true' : 'false';
            } elseif (\is_object($node)) {
                $node = json_decode(json_encode($node), true);
            }
        }

        return $map;
    }

    /**
     * @param $value
     * @return bool
     */
    public static function isBytes($value): bool
    {
        if (!is_array($value)) {
            return false;
        }
        $i = 0;
        foreach ($value as $k => $ord) {
            if ($k !== $i) {
                return false;
            }
            if (!\is_int($ord)) {
                return false;
            }
            if ($ord < 0 || $ord > 255) {
                return false;
            }
            ++$i;
        }

        return true;
    }


    /**
     * Get user agent, if it userAgent is not null, splice it with defaultUserAgent and return, otherwise return
     * defaultUserAgent.
     *
     * @param string $userAgent
     *
     * @return string the string value
     */
    public static function getUserAgent(string $userAgent = ''): string
    {
        if (empty(self::$defaultUserAgent)) {
            self::$defaultUserAgent = sprintf('AlibabaCloud (%s; %s) PHP/%s Core/3.1 TeaDSL/1', PHP_OS, \PHP_SAPI, PHP_VERSION);
        }
        if (!empty($userAgent)) {
            return self::$defaultUserAgent . ' ' . $userAgent;
        }

        return self::$defaultUserAgent;
    }
}
